home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 1 Issue 2 / PDCD-1 - Issue 02.iso / _utilities / utilities / 001 / fue / c / REGION < prev    next >
Text File  |  1991-04-04  |  25KB  |  699 lines

  1. /*
  2.  * The routines in this file
  3.  * deal with the region, that magic space
  4.  * between "." and mark. Some functions are
  5.  * commands. Some functions are just for
  6.  * internal use.
  7.  */
  8. #include        <stdio.h>
  9. #include        "estruct.h"
  10. #include        "etype.h"
  11. #include        "edef.h"
  12. #include        "elang.h"
  13.  
  14. /*      regundent:      undent a region.
  15. */
  16.  
  17. PASCAL NEAR regundent(n)
  18. int n;  /* number of spaces to undent */
  19.  
  20. {
  21.         REGION region;
  22.         LINE *olddotp, *oldmarkp;
  23.         int  olddoto, oldmarko, infolds;
  24.  
  25.         /* check for a valid region first */
  26.         if (getregion(®ion) != TRUE)
  27.                 return(FALSE);
  28.  
  29.         olddotp = curwp->w_dotp;
  30.         olddoto = curwp->w_doto;
  31.         oldmarkp = curwp->w_markp[0];
  32.         oldmarko = curwp->w_marko[0];
  33.  
  34.         /* start at the top of the region.... */
  35.         curwp->w_dotp = region.r_linep;
  36.         curwp->w_doto = region.r_offset;
  37.  
  38.         region.r_size += region.r_offset;
  39.  
  40.         infolds = 0;
  41.  
  42.         /* scan the region... undenting */
  43.         while (region.r_size > 0L) {
  44.                 region.r_size -= llength(curwp->w_dotp) + 1;
  45.                 if ((curwp->w_doto == 0) && (infolds == 0)) {
  46.                         ldelete((long)n, FALSE, FALSE, FALSE);
  47.                         curwp->w_dotp->l_lmargin -= n;
  48.                 }
  49.                 if (infolds > 0) /* line too short for calculation */
  50.                         region.r_size -=n;
  51.                 if (curwp->w_dotp->l_type == LSOEFOLD)
  52.                         infolds++;
  53.                 else if (curwp->w_dotp->l_type == LEOEFOLD)
  54.                         infolds--;
  55.                 curwp->w_dotp = lforw(curwp->w_dotp);
  56.                 curwp->w_doto = 0;
  57.         }
  58.  
  59.         /* place us at the start position */
  60.         curwp->w_dotp = olddotp;
  61.         curwp->w_markp[0] = oldmarkp;
  62.         if (olddotp == region.r_linep) {
  63.                 curwp->w_doto = olddoto;
  64.                 curwp->w_marko[0] = (oldmarko < n) ? 0 : oldmarko - n;
  65.         }
  66.         else {
  67.                 curwp->w_marko[0] = oldmarko;
  68.                 curwp->w_doto = (olddoto < n) ? 0 : olddoto - n;
  69.         }
  70.  
  71.         return(TRUE);
  72. }
  73.  
  74.  
  75. /*      reglines:       how many lines in the current region
  76.                         used by the trim/entab/detab-region commands
  77. */
  78.  
  79. int PASCAL NEAR reglines()
  80.  
  81. {
  82.         register LINE *linep;   /* position while scanning */
  83.         register int n;         /* number of lines in this current region */
  84.         REGION region;
  85.  
  86.         /* check for a valid region first */
  87.         if (getrawregion(®ion) != TRUE)
  88.                 return(0);
  89.  
  90.         /* start at the top of the region.... */
  91.         linep = region.r_linep;
  92.         region.r_size += region.r_offset;
  93.         n = 0;
  94.  
  95.         /* scan the region... counting lines */
  96.         while (region.r_size > 0L) {
  97.                 region.r_size -= llength(linep) + 1;
  98.                 linep = lforw(linep);
  99.                 n++;
  100.         }
  101.  
  102.         /* place us at the beginning of the region */
  103.         curwp->w_dotp = region.r_linep;
  104.         curwp->w_doto = region.r_offset;
  105.  
  106.         return(n);
  107. }
  108.  
  109. /*
  110.  * Kill the region. Ask "getregion"
  111.  * to figure out the bounds of the region.
  112.  * Move "." to the start, and kill the characters.
  113.  * Bound to "C-W".
  114.  * If necessary remove any fold indentation.
  115.  */
  116. PASCAL NEAR killregion(f, n)
  117.  
  118. {
  119.         register int    s;
  120.         REGION          region;
  121.         int             indent;
  122.         int             setfoldbound;
  123.  
  124.         if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
  125.                 return(rdonly());       /* we are in read only mode     */
  126.  
  127.         killedcr = TRUE;
  128.         setfoldbound = FALSE;
  129.  
  130.         if (curwp->w_markp[0] == (LINE *)NULL) {
  131.                 mlwrite(TEXT76);
  132. /*                      "No mark set in this window" */
  133.                 return(FALSE);
  134.         }
  135.  
  136.         /* Start & finish at left margin if at < the left margin */
  137.         if (curwp->w_doto < curwp->w_dotp->l_lmargin)
  138.                 curwp->w_doto = curwp->w_dotp->l_lmargin;
  139.  
  140.         if ((curwp->w_markp[0] != (LINE *)NULL) &&
  141.             (curwp->w_marko[0] < curwp->w_markp[0]->l_lmargin))
  142.                 curwp->w_marko[0] = curwp->w_markp[0]->l_lmargin;
  143.  
  144.         /* check if limits are fold lines, if so set offset to 0 */
  145.         if (curwp->w_dotp->l_type != LNORMAL) {
  146.                 curwp->w_doto = 0; 
  147.                 setfoldbound = TRUE;
  148.         }
  149.         if ((curwp->w_markp[0] != (LINE*)NULL) &&
  150.             (curwp->w_markp[0]->l_type != LNORMAL)) {
  151.                 curwp->w_marko[0] = 0;
  152.                 setfoldbound = TRUE;
  153.         }
  154.  
  155.         /* Don't allow the mark or dot to be on a fold marker if
  156.          * we aren't killing whole lines.
  157.         */
  158.         if (curwp->w_dotp->l_type != LNORMAL) {
  159.                 if (curwp->w_marko[0] > curwp->w_markp[0]->l_lmargin)
  160.                         return(beep());
  161.                 else
  162.                         curwp->w_marko[0] = 0;
  163.         }
  164.             
  165.         if (curwp->w_markp[0]->l_type != LNORMAL) {
  166.                 if (curwp->w_doto > curwp->w_dotp->l_lmargin)
  167.                         return(beep());
  168.                 else
  169.                         curwp->w_doto = 0;
  170.         }
  171.             
  172.         /* call getrawregion first, cos this will check if we cross crease */
  173.         if ((s = getrawregion(®ion)) != TRUE)
  174.                 return(s);
  175.  
  176.         /* Check if prefix removal required */
  177.                 indent = ((curwp->w_dotp == curwp->w_markp[0]) &&
  178.                           (curwp->w_doto >= curwp->w_dotp->l_lmargin) &&
  179.                           (curwp->w_marko[0] >= curwp->w_markp[0]->l_lmargin)) ? 
  180.                          0 : minleftmarg(curwp->w_dotp); 
  181.                 
  182.         if (indent > 0) {
  183.                 regundent(indent);
  184.                 /* recalculate the region */
  185.                 if ((s = getrawregion(®ion)) != TRUE)
  186.                         return(s);
  187.         }
  188.  
  189.         if ((lastflag&CFKILL) == 0)             /* This is a kill type  */
  190.                 kdelete();                      /* command, so do magic */
  191.         thisflag |= CFKILL;                     /* kill buffer stuff.   */
  192.         curwp->w_dotp = region.r_linep;
  193.         curwp->w_doto = region.r_offset;
  194.         s = ldelete(region.r_size, TRUE, TRUE, FALSE);
  195.         curwp->w_dotp->l_lmargin = minleftmarg(curwp->w_dotp);
  196.         if (curwp->w_dotp->l_type == LNORMAL)
  197.                 marginchk(curwp->w_dotp, curwp->w_doto); /* may have killed indent */
  198.         if (curwp->w_doto < curwp->w_dotp->l_lmargin)
  199.                 curwp->w_doto = curwp->w_dotp->l_lmargin;
  200.         killfoldbound = setfoldbound; /* kdelete changes flag */
  201.  
  202.         return(s);
  203. }
  204.  
  205. /*
  206.  * Copy all of the characters in the
  207.  * region to the kill buffer. Don't move dot
  208.  * at all. This is a bit like a kill region followed
  209.  * by a yank. Bound to "M-W".
  210.  * We have to remove any indentation due to folds, copy and
  211.  * then put indentation back.
  212.  */
  213. PASCAL NEAR copyregion(f, n)
  214. {
  215.         register LINE   *linep;
  216.         register int    loffs;
  217.         register int    s;
  218.         REGION          region;
  219.         int             indent;
  220.         int             setfoldbound;
  221.  
  222.         setfoldbound = FALSE;
  223.         killedcr = TRUE;
  224.  
  225.         /* check if limits are fold lines, if so set offset to 0 */
  226.  
  227.         if (curwp->w_dotp->l_type != LNORMAL) {
  228.                 curwp->w_doto = 0;
  229.                 setfoldbound = TRUE;
  230.         }
  231.         if ((curwp->w_markp[0] != (LINE*)NULL) &&
  232.             (curwp->w_markp[0]->l_type != LNORMAL)) {
  233.                 curwp->w_marko[0] = 0;
  234.                 setfoldbound = TRUE;
  235.         }
  236.         if ((s=getrawregion(®ion)) != TRUE)
  237.                 return(s);
  238.         if ((lastflag&CFKILL) == 0)             /* Kill type command.   */
  239.                 kdelete();
  240.         thisflag |= CFKILL;
  241.         linep = region.r_linep;                 /* Current line.        */
  242.         if (region.r_offset < linep->l_lmargin) { /* move to margin */
  243.                 loffs = linep->l_lmargin;
  244.                 region.r_size -= (linep->l_lmargin - region.r_offset);
  245.         }
  246.         else
  247.                 loffs = region.r_offset;     /* Current offset.      */
  248.  
  249.         while (region.r_size-- > 0) {
  250.                 if (loffs == llength(linep)) {  /* End of line.         */
  251.                         if ((s=kinsert('\r')) != TRUE)
  252.                                 return(s);
  253.                         linep = linep->l_fp;
  254.                         loffs = region.r_linep->l_lmargin;
  255.                         region.r_size -= loffs;
  256.                 } else {                        /* Middle of line.      */
  257.                         if ((s=kinsert(lgetc(linep, loffs))) != TRUE)
  258.                                 return(s);
  259.                         ++loffs;
  260.                 }
  261.         }
  262.         killfoldbound = setfoldbound; /* kdelete changes flag */
  263.         mlwrite(TEXT70);
  264. /*              "[region copied]" */
  265.         return(TRUE);
  266. }
  267.  
  268. /*
  269.  * Lower case region. Zap all of the upper
  270.  * case characters in the region to lower case. Use
  271.  * the region code to set the limits. Scan the buffer,
  272.  * doing the changes. Call "lchange" to ensure that
  273.  * redisplay is done in all buffers. Bound to
  274.  * "C-X C-L".
  275.  */
  276. PASCAL NEAR lowerregion(f, n)
  277. {
  278.         register LINE   *linep;
  279.         register int    loffs;
  280.         register int    s;
  281.         int c;
  282.         REGION          region;
  283.  
  284.         if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
  285.                 return(rdonly());       /* we are in read only mode     */
  286.         if ((s=getregion(®ion)) != TRUE)
  287.                 return(s);
  288.         lchange(WFHARD);
  289.         linep = region.r_linep;
  290.         loffs = region.r_offset;
  291.         while (region.r_size--) {
  292.                 if (loffs == llength(linep)) {
  293.                         linep = lforw(linep);
  294.                         loffs = 0;
  295.                 } else {
  296.                         c = lgetc(linep, loffs);
  297.                         c = lowerc(c);
  298.                         lputc(linep, loffs, c);
  299.                         ++loffs;
  300.                 }
  301.         }
  302.         return(TRUE);
  303. }
  304.  
  305. /*
  306.  * Upper case region. Zap all of the lower
  307.  * case characters in the region to upper case. Use
  308.  * the region code to set the limits. Scan the buffer,
  309.  * doing the changes. Call "lchange" to ensure that
  310.  * redisplay is done in all buffers. Bound to
  311.  * "C-X C-L".
  312.  */
  313. PASCAL NEAR upperregion(f, n)
  314. {
  315.         register LINE   *linep;
  316.         register int    loffs;
  317.         register int    s;
  318.         int c;
  319.         REGION          region;
  320.  
  321.         if (curbp->b_mode&MDVIEW)       /* don't allow this command if  */
  322.                 return(rdonly());       /* we are in read only mode     */
  323.         if ((s=getregion(®ion)) != TRUE)
  324.                 return(s);
  325.         lchange(WFHARD);
  326.         linep = region.r_linep;
  327.         loffs = region.r_offset;
  328.         while (region.r_size--) {
  329.                 if (loffs == llength(linep)) {
  330.                         linep = lforw(linep);
  331.                         loffs = 0;
  332.                 } else {
  333.                         c = lgetc(linep, loffs);
  334.                         c = upperc(c);
  335.                         lputc(linep, loffs, c);
  336.                         ++loffs;
  337.                 }
  338.         }
  339.         return(TRUE);
  340. }
  341.  
  342. /*      Narrow-to-region (^X-<) makes all but the current region in
  343.         the current buffer invisable and unchangable
  344. */
  345.  
  346. PASCAL NEAR narrow(f, n)
  347.  
  348. {
  349.         register int status;    /* return status */
  350.         BUFFER *bp;             /* buffer being narrowed */
  351.         WINDOW *wp;             /* windows to fix up pointers in as well */
  352.         REGION creg;            /* region boundry structure */
  353.         int cmark;              /* current mark */
  354.  
  355.         /* find the proper buffer and make sure we aren't already narrow */
  356.         bp = curwp->w_bufp;             /* find the right buffer */
  357.         if (bp->b_flag&BFNAROW) {
  358.                 mlwrite(TEXT71);
  359. /*                      "%%This buffer is already narrowed" */
  360.                 return(FALSE);
  361.         }
  362.  
  363.         /* find the boundries of the current region */
  364.         if ((status=getregion(&creg)) != TRUE)
  365.                 return(status);
  366.         curwp->w_dotp = creg.r_linep;   /* only by full lines please! */
  367.         curwp->w_doto = 0;
  368.         creg.r_size += (long)creg.r_offset;
  369.         if (creg.r_size <= (long)curwp->w_dotp->l_used) {
  370.                 mlwrite(TEXT72);
  371. /*                      "%%Must narrow at least 1 full line" */
  372.                 return(FALSE);
  373.         }
  374.  
  375.         /* archive the top fragment */
  376.         if (bp->b_linep->l_fp != creg.r_linep) {
  377.                 bp->b_topline = bp->b_linep->l_fp;
  378.                 creg.r_linep->l_bp->l_fp = (LINE *)NULL;
  379.                 bp->b_linep->l_fp = creg.r_linep;
  380.                 creg.r_linep->l_bp = bp->b_linep;
  381.         }
  382.  
  383.         /* move forward to the end of this region
  384.            (a long number of bytes perhaps) */
  385.         while (creg.r_size > (long)32000) {
  386.                 forwchar(TRUE, 32000);
  387.                 creg.r_size -= (long)32000;
  388.         }
  389.         forwchar(TRUE, (int)creg.r_size);
  390.         curwp->w_doto = 0;              /* only full lines! */
  391.  
  392.         /* archive the bottom fragment */
  393.         if (bp->b_linep != curwp->w_dotp) {
  394.                 bp->b_botline = curwp->w_dotp;
  395.                 bp->b_botline->l_bp->l_fp = bp->b_linep;
  396.                 bp->b_linep->l_bp->l_fp = (LINE *)NULL;
  397.                 bp->b_linep->l_bp = bp->b_botline->l_bp;
  398.         }
  399.  
  400.         /* let all the proper windows be updated */
  401.         wp = wheadp;
  402.         while (wp) {
  403.                 if (wp->w_bufp == bp) {
  404.                         wp->w_linep = creg.r_linep;
  405.                         wp->w_dotp = creg.r_linep;
  406.                         wp->w_doto = 0;
  407.                         for (cmark = 0; cmark < NMARKS; cmark++) {
  408.                                 wp->w_markp[cmark] = creg.r_linep;
  409.                                 wp->w_marko[cmark] = 0;
  410.                         }
  411.                         wp->w_flag |= (WFHARD|WFMODE);
  412.                 }
  413.                 wp = wp->w_wndp;
  414.         }
  415.  
  416.         /* and now remember we are narrowed */
  417.         bp->b_flag |= BFNAROW;
  418.         mlwrite(TEXT73);
  419. /*              "[Buffer is narrowed]" */
  420.         return(TRUE);
  421. }
  422.  
  423. /*      widen-from-region (^X->) restores a narrowed region     */
  424.  
  425. PASCAL NEAR widen(f, n)
  426.  
  427. {
  428.         LINE *lp;       /* temp line pointer */
  429.         BUFFER *bp;     /* buffer being narrowed */
  430.         WINDOW *wp;     /* windows to fix up pointers in as well */
  431.  
  432.         /* find the proper buffer and make sure we are narrow */
  433.         bp = curwp->w_bufp;             /* find the right buffer */
  434.         if ((bp->b_flag&BFNAROW) == 0) {
  435.                 mlwrite(TEXT74);
  436. /*                      "%%This buffer is not narrowed" */
  437.                 return(FALSE);
  438.         }
  439.  
  440.         /* recover the top fragment */
  441.         if (bp->b_topline != (LINE *)NULL) {
  442.                 lp = bp->b_topline;
  443.                 while (lp->l_fp != (LINE *)NULL)
  444.                         lp = lp->l_fp;
  445.                 lp->l_fp = bp->b_linep->l_fp;
  446.                 lp->l_fp->l_bp = lp;
  447.                 bp->b_linep->l_fp = bp->b_topline;
  448.                 bp->b_topline->l_bp = bp->b_linep;
  449.                 bp->b_topline = (LINE *)NULL;
  450.         }
  451.  
  452.         /* recover the bottom fragment */
  453.         if (bp->b_botline != (LINE *)NULL) {
  454.                 lp = bp->b_botline;
  455.                 while (lp->l_fp != (LINE *)NULL)
  456.                         lp = lp->l_fp;
  457.                 lp->l_fp = bp->b_linep;
  458.                 bp->b_linep->l_bp->l_fp = bp->b_botline;
  459.                 bp->b_botline->l_bp = bp->b_linep->l_bp;
  460.                 bp->b_linep->l_bp = lp;
  461.                 bp->b_botline = (LINE *)NULL;
  462.         }
  463.  
  464.         /* let all the proper windows be updated */
  465.         wp = wheadp;
  466.         while (wp) {
  467.                 if (wp->w_bufp == bp)
  468.                         wp->w_flag |= (WFHARD|WFMODE);
  469.                 wp = wp->w_wndp;
  470.         }
  471.         /* and now remember we are not narrowed */
  472.         bp->b_flag &= (~BFNAROW);
  473.         mlwrite(TEXT75);
  474. /*              "[Buffer is widened]" */
  475.         return(TRUE);
  476. }
  477.  
  478. /*
  479.  * This routine figures out the bounds of the region in the current
  480.  * window, and fills in the fields of the "REGION" structure pointed to by
  481.  * "rp". Because the dot and mark are usually very close together, we scan
  482.  * outward from dot looking for mark. This should save time. Return a
  483.  * standard code. Callers of this routine should be prepared to get an
  484.  * "ABORT" status; we might make this have the confirm thing later.
  485.  */
  486.  
  487. PASCAL NEAR getregion(rp)
  488.  
  489. register REGION *rp;
  490.  
  491. {
  492.         register LINE   *flp;
  493.         register LINE   *blp;
  494.         long fsize;
  495.         long bsize;
  496.  
  497.         if (curwp->w_markp[0] == (LINE *)NULL) {
  498.                 mlwrite(TEXT76);
  499. /*                      "No mark set in this window" */
  500.                 return(FALSE);
  501.         }
  502.         if (curwp->w_dotp == curwp->w_markp[0]) {
  503.                 rp->r_linep = curwp->w_dotp;
  504.                 if (curwp->w_doto < curwp->w_marko[0]) {
  505.                         rp->r_offset = curwp->w_doto;
  506.                         rp->r_size = (long)(curwp->w_marko[0]-curwp->w_doto);
  507.                 } else {
  508.                         rp->r_offset = curwp->w_marko[0];
  509.                         rp->r_size = (long)(curwp->w_doto-curwp->w_marko[0]);
  510.                 }
  511.                 return(TRUE);
  512.         }
  513.         blp = curwp->w_dotp;
  514.         bsize = (long)curwp->w_doto;
  515.         flp = curwp->w_dotp;
  516.         fsize = (long)(llength(flp)-curwp->w_doto+1);
  517.         while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
  518.                 if (flp != curbp->b_linep) {
  519.                         flp = lforw(flp);
  520.                         if (flp == curwp->w_markp[0]) {
  521.                                 rp->r_linep = curwp->w_dotp;
  522.                                 rp->r_offset = curwp->w_doto;
  523.                                 rp->r_size = fsize+curwp->w_marko[0];
  524.                                 return(TRUE);
  525.                         }
  526.                         fsize += llength(flp)+1;
  527.                 }
  528.                 if (lback(blp) != curbp->b_linep) {
  529.                         blp = lback(blp);
  530.                         bsize += llength(blp)+1;
  531.                         if (blp == curwp->w_markp[0]) {
  532.                                 rp->r_linep = blp;
  533.                                 rp->r_offset = curwp->w_marko[0];
  534.                                 rp->r_size = bsize - curwp->w_marko[0];
  535.                                 return(TRUE);
  536.                         }
  537.                 }
  538.         }
  539.         mlwrite(TEXT77);
  540. /*              "Bug: lost mark" */
  541.         return(FALSE);
  542. }
  543.  
  544.  
  545. /*
  546.  * This routine figures out the bounds of the region in the current
  547.  * window, IT DESCENDS INTO FOLDS, and fills in the fields of the "REGION"
  548.  * structure pointed to by "rp". Because the dot and mark are usually very
  549.  * close together, we scan outward from dot looking for mark. 
  550.  * This should save time. Return a standard code. Callers of 
  551.  * this routine should be prepared to get an
  552.  * "ABORT" status; we might make this have the confirm thing later.
  553.  * This routine will return an error if an incomplete open fold is 
  554.  * within the region.
  555.  */
  556.  
  557. PASCAL NEAR getrawregion(rp)
  558.  
  559. register REGION *rp;
  560.  
  561. {
  562.         register LINE   *flp;
  563.         register LINE   *blp;
  564.         long fsize;
  565.         long bsize;
  566.         int  ffcnt, fferr, bfcnt, bferr;
  567.  
  568.         if (curwp->w_markp[0] == (LINE *)NULL) {
  569.                 mlwrite(TEXT76);
  570. /*                      "No mark set in this window" */
  571.                 return(FALSE);
  572.         }
  573.         if (curwp->w_dotp == curwp->w_markp[0]) {
  574.                 if (curwp->w_dotp->l_type != LNORMAL)
  575.                         return(beep());
  576.                 rp->r_linep = curwp->w_dotp;
  577.                 if (curwp->w_doto < curwp->w_marko[0]) {
  578.                         rp->r_offset = curwp->w_doto;
  579.                         rp->r_size = (long)(curwp->w_marko[0]-curwp->w_doto);
  580.                 } else {
  581.                         rp->r_offset = curwp->w_marko[0];
  582.                         rp->r_size = (long)(curwp->w_doto-curwp->w_marko[0]);
  583.                 }
  584.                 return(TRUE);
  585.         }
  586.  
  587.         /* initialise fold error counts and markers */
  588.         /* since search is bi-directional, errors may be virtual */
  589.         if ((curwp->w_dotp->l_type == LSOEFOLD) ||
  590.             (curwp->w_dotp->l_type == LSOFOLD)) {
  591.                 if (curwp->w_doto > curwp->w_dotp->l_lmargin)
  592.                         curwp->w_doto = loffset(curwp->w_dotp);
  593.                 bfcnt = 0;
  594.                 ffcnt = 1;
  595.                 bferr = fferr = FALSE;
  596.         }
  597.         else if (curwp->w_dotp->l_type == LEOEFOLD) {
  598.                 if (curwp->w_doto > curwp->w_dotp->l_lmargin)
  599.                         curwp->w_doto = curwp->w_dotp->l_used;
  600.                 bfcnt = 0;
  601.                 ffcnt = -1;
  602.                 bferr = FALSE;
  603.                 fferr = TRUE;
  604.         }
  605.         else {
  606.                 bfcnt = ffcnt = 0;
  607.                 bferr = fferr = FALSE;
  608.         }
  609.  
  610.         blp = curwp->w_dotp;
  611.         bsize = (long)curwp->w_doto;
  612.         flp = curwp->w_dotp;
  613.         fsize = (long)(llength(flp)-curwp->w_doto+1);
  614.  
  615.         while (flp!=curbp->b_linep || blp->l_bp !=curbp->b_linep) {
  616.                 if (flp != curbp->b_linep) {
  617.                         flp = flp->l_fp;
  618.                         if (flp == curwp->w_markp[0]) {
  619.                                 rp->r_linep = curwp->w_dotp;
  620.                                 rp->r_offset = curwp->w_doto;
  621.                                 rp->r_size = fsize+curwp->w_marko[0];
  622.                                 if (ffcnt || fferr)
  623.                                         mlwrite(TEXT232);
  624. /*                                      "%%Region contains folds" */
  625.                                 return(!ffcnt && !fferr);
  626.                         }
  627.                         /* going forward we don't want to check last line */
  628.                         else if ((flp->l_type == LSOEFOLD) ||
  629.                                  (flp->l_type == LSOFOLD))
  630.                                 ffcnt++;
  631.                         else if ((flp->l_type == LEOEFOLD) ||
  632.                                  (flp->l_type == LEOFOLD))
  633.                                 fferr = fferr | (--ffcnt < 0);
  634.                         fsize += llength(flp)+1;
  635.                 }
  636.                 if (blp->l_bp != curbp->b_linep) {
  637.                         blp = blp->l_bp;
  638.                         if ((blp->l_type == LSOEFOLD) ||
  639.                             (blp->l_type == LSOFOLD))
  640.                                 bferr = bferr | (--bfcnt < 0);
  641.                         else if ((blp->l_type == LEOEFOLD) ||
  642.                                  (blp->l_type == LEOFOLD))
  643.                                 bfcnt++;
  644.                         bsize += llength(blp)+1;
  645.                         if (blp == curwp->w_markp[0]) {
  646.                                 rp->r_linep = blp;
  647.                                 rp->r_offset = curwp->w_marko[0];
  648.                                 rp->r_size = bsize - curwp->w_marko[0];
  649.                                 if (bfcnt || bferr)
  650.                                         mlwrite(TEXT232);
  651. /*                                      "%%Region contains folds" */
  652.                                 return(!bfcnt && !bferr);
  653.                         }
  654.                 }
  655.         }
  656.         mlwrite(TEXT77);
  657. /*              "Bug: lost mark" */
  658.         return(FALSE);
  659. }
  660.  
  661. char *PASCAL NEAR getreg()      /* return some of the contents of the current region */
  662.  
  663. {
  664.         register char * sp;     /* ptr into temporary buffer */
  665.         register LINE *linep;
  666.         register int loffs;
  667.         register int s;
  668.         REGION region;
  669.         char value[NSTRING];    /* temp buffer for value */
  670.  
  671.         /* get the region limits */
  672.         if ((s=getregion(®ion)) != TRUE)
  673.                 return(errorm);
  674.         linep = region.r_linep;                 /* Current line.        */
  675.         loffs = region.r_offset;                /* Current offset.      */
  676.  
  677.         /* don't let the region be larger than a string can hold */
  678.         if (region.r_size >= NSTRING)
  679.                 region.r_size = NSTRING - 1;
  680.  
  681.         /* scan the region, record the characters */
  682.         sp = value;
  683.         while (region.r_size--) {
  684.                 if (loffs == llength(linep)) {  /* End of line.         */
  685.                         *sp++ = '\r';
  686.                         linep = lforw(linep);
  687.                         loffs = 0;
  688.                 } else {                        /* Middle of line.      */
  689.                         *sp++ = lgetc(linep, loffs);
  690.                         ++loffs;
  691.                 }
  692.         }
  693.  
  694.         /* and return the constructed value */
  695.         *sp = 0;
  696.         return(value);
  697. }
  698.  
  699.